﻿using System;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace Light.Utility.Security
{
    /// <summary>
    /// 不可逆加密类
    /// </summary>
    public class IrreversibleCryptor
    {
        /// <summary>
        /// 用SHA1加密密码 撒盐法 
        /// 24位字节长度（20位SHA1+4位“盐”）
        /// </summary>
        /// <param name="input">输入值</param>
        /// <returns></returns>
        public static byte[] SaltPassword(string input)
        {

            byte[] salt = new byte[4];

            SHA1 sha1 = SHA1.Create();
            byte[] inputBytes = UTF8Encoding.Default.GetBytes(input);
            byte[] hashpwd = sha1.ComputeHash(inputBytes);
            byte[] saltedPwd = new byte[hashpwd.Length + 4];

            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(salt);
            hashpwd.CopyTo(saltedPwd, 0);
            salt.CopyTo(saltedPwd, hashpwd.Length);
            return saltedPwd;
        }

        /// <summary>
        /// 获取加密后的字符串
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string GetSaltedString(string input)
        {
            return Convert.ToBase64String(SaltPassword(input));
        }

        /// <summary>
        /// 验证输入字符串与加密后的字符串是否一致
        /// </summary>
        /// <param name="input"></param>
        /// <param name="saltedString"></param>
        /// <returns></returns>
        public static bool VarifyString(string input, string saltedString)
        {
            if (String.IsNullOrEmpty(saltedString)) return false;

            byte[] saltedByt = Convert.FromBase64String(saltedString);
            return VarifySaltPassword(input, saltedByt);
        }

        /// <summary>
        /// 验证密码 撒盐法
        /// </summary>
        /// <param name="input">输入密码</param>
        /// <param name="hashBytes">原密码</param>        
        /// <returns></returns>
        public static bool VarifySaltPassword(string input, byte[] hashBytes)
        {
            byte[] inputBytes = SaltPassword(input);
            //取出数据库中的密码与输入的密码进行比较
            if (hashBytes == null && input == string.Empty)
            {
                return true;
            }
            else if (hashBytes == null || inputBytes == null)
            {
                return false;
            }
            //比较前20位，去除后4位
            for (int i = 0; i < inputBytes.Length - 4; i++)
            {
                if (hashBytes[i] != inputBytes[i])
                {
                    return false;
                }
            }
            return true;
        }


        /// <summary>
        /// MD5加密（穷举法可破解）
        /// </summary>
        /// <param name="input">输入字符</param>
        /// <returns></returns>
        public static string GetMd5Hash(string input)
        {
            using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
            {
                return BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(input))).Replace("-", "");
            }
        }


        /// <summary>
        /// MD5验证输入
        /// </summary>
        /// <param name="input">输入字符</param>
        /// <param name="hash">原Hash字符</param>
        /// <returns></returns>
        public static bool VerifyMd5Hash(string input, string hash)
        {
            string hashOfInput = GetMd5Hash(input);
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;
            return comparer.Compare(hashOfInput, hash) == 0 ? true : false;
        }








        /// <summary> 
        /// 获取信息的Hash值
        /// </summary>
        /// <param name="message">需要哈希的字符串</param>
        /// <returns></returns>
        public byte[] GetHash(string message)
        {

            byte[] messagebytes = Encoding.UTF8.GetBytes(message);
            //X509Certificate2 x509 = new X509Certificate2(path+ "Certificate\\zzServer.p12", "mypassword");
            //RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)x509.PrivateKey; ;
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            //对要签名的数据进行哈希
            byte[] hashbytes = sha1.ComputeHash(messagebytes);
            //输出hash加密数据
            //string hash = BitConverter.ToString(hashbytes).Replace("-", "");
            return hashbytes;

        }


        /// <summary>
        /// 用私钥对哈希值进行签名，产生摘要
        /// </summary>
        /// <param name="hashbytes">哈希值</param>
        /// <returns></returns>
        public byte[] SignByPrivateKey(byte[] hashbytes)
        {

            X509Certificate2 x509 = new X509Certificate2("C:\\" + "Certificate\\zzServer.p12", "mypassword");
            RSAPKCS1SignatureFormatter signe = new RSAPKCS1SignatureFormatter();
            //设置签名用到的私钥
            signe.SetKey(x509.PrivateKey);
            //设置签名算法
            signe.SetHashAlgorithm("SHA1");
            //创建签名
            byte[] signreslut = signe.CreateSignature(hashbytes);
            //string encrypt = BitConverter.ToString(reslut).Replace("-", "");
            return signreslut;
        }


        /// <summary>
        /// 用公钥对签名进行验证
        /// </summary>
        /// <param name="hashbytes">摘要的哈希值</param>
        /// <param name="messagebytes">对哈希值进行签名后的值</param>
        /// <returns></returns>
        public bool VerifySign(byte[] hashbytes, byte[] signreslut)
        {

            // 验签
            X509Certificate2 x509 = new X509Certificate2("C:\\" + "Certificate\\zzServer.cer", "mypassword");
            RSACryptoServiceProvider oRSA4 = new RSACryptoServiceProvider();
            oRSA4.FromXmlString(x509.PublicKey.Key.ToXmlString(false));
            ////传入原始数据和签名数据，进行验证
            //bool bVerify = oRSA4.VerifyData(messagebytes, "SHA1", signreslut);
            //Response.Write(bVerify);
            //传入加密的hash数据和签名数据，进行验证
            //数据篡改验证
            //hashbytes[0] = 11;
            bool bHash = oRSA4.VerifyHash(hashbytes, "SHA1", signreslut);

            return bHash;

        }


    }

}
